﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace CoVanHocTapData.Infrastructure
{
    public class EncryptPassword
    {
        public EncryptPassword() { }

        public static string encryptString(string strToEncrypt)
        {
            System.Text.UTF8Encoding ue = new System.Text.UTF8Encoding();
            byte[] bytes = ue.GetBytes(strToEncrypt);

            // encrypt bytes
            System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
            byte[] hashBytes = md5.ComputeHash(bytes);

            // Convert the encrypted bytes back to a string (base 16)
            string hashString = "";

            for (int i = 0; i < hashBytes.Length; i++)
            {
                hashString += Convert.ToString(hashBytes[i], 16).PadLeft(2, '0');
            }

            return hashString.PadLeft(32, '0');
        }

        /// <param name="strToEncryp">the string to hash</param>
        /// <param name="Algorithm">the Algorithm of choice. 0 for MD5, 1 for SHA-1</param>
        /// <returns></returns>
        public static string encryptString(string strToEncryp, int Algorithm)
        {
            if (Algorithm == 1)
            {
                System.Text.UTF8Encoding ue = new System.Text.UTF8Encoding();
                byte[] bytes = ue.GetBytes(strToEncryp);

                // encrypt bytes
                System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
                SHA1CryptoServiceProvider SHA = new SHA1CryptoServiceProvider();
                byte[] hashBytes = SHA.ComputeHash(bytes);

                // Convert the encrypted bytes back to a string (base 16)
                string hashString = "";

                for (int i = 0; i < hashBytes.Length; i++)
                {
                    hashString += Convert.ToString(hashBytes[i], 16).PadLeft(2, '0');
                }

                return hashString.PadLeft(32, '0');
            }
            else
            {
                return encryptString(strToEncryp);
            }

        }
        /// <summary>
        /// converts the MD5 of SHA-1 result byte[] to a string representative
        /// </summary>
        /// <param name="RawStringBytes">the Raw bytes to hash</param>
        /// <returns></returns>
        public static string encryptString(byte[] RawStringBytes)
        {

            string hashString = "";
            for (int i = 0; i < RawStringBytes.Length; i++)
            {
                hashString += Convert.ToString(RawStringBytes[i], 16).PadLeft(2, '0');
            }

            return hashString.PadLeft(32, '0');

        }
        /// <summary>
        /// For MD5 hashing of files
        /// </summary>
        /// <param name="filepath">the filepath of the file to hash</param>
        /// <returns></returns>
        public static string Md5File(string filepath)
        {
            FileStream filestrm = new FileStream(filepath, FileMode.Open);
            byte[] md5byte = new byte[filestrm.Length];

            filestrm.Read(md5byte, 0, Convert.ToInt32(filestrm.Length.ToString()));
            byte[] ResultHash = HashByte(md5byte);


            string hashString = "";

            for (int i = 0; i < ResultHash.Length; i++)
            {
                hashString += Convert.ToString(ResultHash[i], 16).PadLeft(2, '0');
            }
            filestrm.Close();
            return hashString.PadLeft(32, '0');

        }




        public static byte[] HashByte(byte[] bytes)
        {

            // encrypt bytes
            System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
            byte[] hashBytes = md5.ComputeHash(bytes);

            // Convert the encrypted bytes back to a string (base 16)

            return hashBytes;
        }

        public static byte[] HashByte(byte[] bytes, int Algorithm)
        {
            byte[] hashBytes = null;

            if (Algorithm == 0)//MD5
            {

                System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
                hashBytes = md5.ComputeHash(bytes);
            }
            else if (Algorithm == 1)//SHA-1
            {//SHA-1
                // Convert the encrypted bytes back to a string (base 16)
                SHA1CryptoServiceProvider SHS = new SHA1CryptoServiceProvider();
                hashBytes = SHS.ComputeHash(bytes);
            }
            else
            {
                return null;
            }
            return hashBytes;
        }
        /// <summary>
        /// Mã hóa chuỗi đơn giản để lưu xuống cookie đồng thời cũng là hàm giải mã nếu gọi lại, 
        /// Giải thuật:Nữa chuỗi đầu lấy kí tự trước và đảo ra sau, nữa chuỗi sau lấy ký tự sau và đảo ra trước, ký tự giữa (nếu có) thì giữ nguyên. Ví dụ chuỗi: "deycm" sẽ chuyển thành "dnycd"
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public static string EncryptSimple(string text)
        {
            string s = "";
            int n = (text.Length + 1) / 2;
            for (int i = n; i < text.Length; i++)
                s += (char)(text[i] + 1);
            if (text.Length % 2 == 1)
            {
                s += text[text.Length / 2];
                n--;
            }
            for (int i = 0; i < n; i++)
                s += (char)(text[i] - 1);
            return s;
        }
        public static string ReplaceUsername(string name, bool add, string ExtraString)
        {
            string[] extra = ExtraString.Split('*');

            if (!add)
            {
                if (!HasExtraString(name, ExtraString))
                    return name;
                name = name.Substring(extra[0].Length);
                name = name.Substring(0, name.IndexOf(extra[1]));
                return name;
            }
            else name = extra[0] + name + extra[1];
            return name;
        }
        /// <summary>
        /// Kiểm tra xem name có áp ExtraString chưa
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static bool HasExtraString(string name, string ExtraString)
        {
            string[] extra = ExtraString.Split('*');
            return name.StartsWith(extra[0]) && name.EndsWith(extra[1]);
        }
        /// <summary>
        /// mã hóa username: Thêm chuỗi extra sau đó mã hóa trả về chuỗi kết quả
        /// giải mã username: Gọi hàm mã hóa để giải mã, loại bỏ chuỗi extra
        /// </summary>
        /// <param name="name">Tên username cần mã hóa hoặc chuỗi có username đã mã hóa</param>
        /// <returns>Chuỗi mã hóa có username hoặc user đã giải mã</returns>
        public static string EncryptOrDecryptUsername(string name, bool doEncrypt, string ExtraString)
        {
            if (!doEncrypt)//nếu là giải mã
                return ReplaceUsername(EncryptPassword.EncryptSimple(name), false, ExtraString);
            //ngược lại chưa có extrastring tức là name chưa mã hóa, cần mã hóa name này
            return EncryptPassword.EncryptSimple(ReplaceUsername(name, true, ExtraString));
        }
    }
}
